home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 8077 < prev    next >
Encoding:
Text File  |  1996-08-05  |  6.8 KB  |  214 lines

  1. Path: anvil.ugrad.cs.ubc.ca!not-for-mail
  2. From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: line intersection in C
  5. Date: 29 Feb 1996 14:49:49 -0800
  6. Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
  7. Message-ID: <4h5aidINN76e@anvil.ugrad.cs.ubc.ca>
  8. References: <1996Feb25.230142.29689@dcs.warwick.ac.uk> <3134933A.AB9@computek.net> <4h31v6$68q@sun001.spd.dsccc.com>
  9. NNTP-Posting-Host: anvil.ugrad.cs.ubc.ca
  10.  
  11. In article <4h31v6$68q@sun001.spd.dsccc.com>,
  12. Mike McCarty <jmccarty@spd.dsccc.com> wrote:
  13. >In article <3134933A.AB9@computek.net>,
  14. >robert jacobs and jason jacobs  <robertj@computek.net> wrote:
  15. >)Daniel Castillo Molero wrote:
  16. >)> 
  17. >)> Hello,
  18. >)> 
  19. >)> I wonder if anybody can help me to find an algorithm in C to detect whether
  20. >)> two line segments intersect properly (I don't know if this is the correct
  21. >)> terminology, but by proper intersection I mean that the intersection is
  22. >)> not in the extreme of any of them and that one does not lie on top of
  23. >)> the other).
  24. >)> I need to test intersection just for line segments whose slope is a multiple
  25. >)> of 45 degrees, which I suppose may simplify the solution.
  26. >)> 
  27. >)> I would greatly appreciate any sort of help.
  28. >)> 
  29. >)> Daniel Castillo.
  30. >)> 
  31. >)> danmol@dcs.warwick.ac.uk
  32. >)> 
  33. >)> --
  34. >)> * Daniel Castillo.  D.C.Molero@dcs.warwick.ac.uk *
  35. >)
  36. >)Plug the end points of line segements into the equation for a line.
  37. >)Calculate the slope of the lines.  If the slopes are defferent the lines 
  38. >)will intersect.
  39. >)
  40. >)Bob Jacobs
  41. >
  42. >
  43. >Bob, you really should have read the post before responding to it. They
  44. >guy is talking about line segments. This is not a simple problem.
  45.  
  46. I did not notice that either, by the way. The subject of the post is ``line
  47. intersection'', after all. :)
  48.  
  49. >Here's a try:
  50. >
  51. >First, sort the endpoints of each of the two lines by x coordinates. If
  52. >the largest x for the first line is less than the smallest x for the
  53. >other, then there is no intersection (takes two checks). You can also
  54. >check the y's the same way.
  55. >
  56. >Now, since the points are sorted by x's, you can check the slopes by
  57. >just seeing the direction of change. If the slopes are the same, then
  58. >no "proper" intersection is possible.
  59. >
  60. >Now comes the hard part, I guess. I think that the best way may be to
  61. >use distances. Compute the equation of one of the lines. Find the
  62. >distances from the endpoints of the other line to the line you
  63. >computed. If one is negative, and the other is positive, you have a
  64. >real intersection. If they are of the same sign, then you have no
  65. >intersection. If one of the distances is zero, then you have a
  66. >degenerate T intersection.
  67. >
  68. >If a line has equation 
  69. >
  70. >    Ax + By + C = 0
  71.  
  72. In this case, the implicit representation is no longer quite as fruitful as in
  73. my solution of the problem for determining whether two lines intersect.
  74.  
  75.  
  76. >then the distance function of a given point (x,y) to the line is
  77. >
  78. >    distance(x,y) = Ax + By + C
  79. >
  80. >If the distance is 0, then the point is on the line, don't you see.
  81. >
  82. >This is something I just came up with as fast as I could type. There may
  83. >be (probably is?) a better way.
  84.  
  85.  
  86. You can represent the line segements parametrically. That is, 
  87.  
  88.     x = At + B
  89.     y = Ct + D
  90.  
  91. The fact that we have a line segment is expressed by limits on the parameter t.
  92. The coefficients can (and probably should) be chosen so that t varies over the
  93. interval [0,1].
  94.  
  95. Finding whether the line segments intersect is akin to finding a pair of
  96. parameters s and t such that if s is a parameter for one segment, and t is the
  97. parameter for the other segments, they both produce the same point. 
  98.  
  99. Such paremetric intersection tests are frequently done in ray-tracing.
  100.  
  101. As an optimization, you can use the bounding boxes of the line segments to do
  102. early rejection tests. If the bounding boxes of the two line segments do not
  103. overlap, the segments cannot intersect.
  104.  
  105.  
  106. I vaguely recall an algorithm which checks whether one line segment _straddles_
  107. the line in which the other segment lies. If it does not, the lines cannot
  108. intersect. If the other line also straddles the first, they do intersect.
  109.  
  110. To check whether a line segment straddles a line, you need to know a two points
  111. on the line (which is readily available if you have both line segments
  112. represented as a pair of endpoints).
  113.  
  114. You take the point on the line, and form a vector to each of the end points of
  115. the line segment.  YOu also form a third vector, from one point to the line to
  116. another point on the line---i.e. a vector in the direction of the line.
  117.  
  118. You cross each of the two original vectors with the one that lies in the line.
  119. If the cross products have opposite signs, it means that one point lies to the
  120. left, and one to the right, and therefore the line segment straddles the line.
  121.  
  122. You reverse the roles of the line segment, and repeat the straddle test.  If it
  123. is successful on both counts, you have an intersection. Of course, in the
  124. parametric method, you would also have computed where this intersection lies.
  125.  
  126.  
  127. The following is just jamming off the top of my head. To make it relevant to
  128. comp.lang.c, I will try to use a lot of cool ANSI stuff like passing structures
  129. around.
  130.  
  131. typedef double coord_t;
  132.  
  133. typedef struct point {
  134.     coord_t x;
  135.     coord_t y;
  136. } point_t, vector_t;
  137.  
  138. typedef struct segment {
  139.     point_t p;
  140.     point_t q;
  141. } segment_t;
  142.  
  143. #define cross(P,Q) ((P).x * (Q).y - (Q).x * (P).y)
  144. #define sub(P,Q) ((P).x -= (Q).x, (P).y -= (Q).y)
  145.  
  146. /*
  147.  * bounding box rejection
  148.  * returns 0 if reject, 1 if accept
  149.  */
  150.  
  151. int bounding(segment_t *a, segment_t *b)
  152. {
  153.     /* too trivial to bother with */
  154.     return 1; /* :) */
  155. }
  156.  
  157. /*
  158.  * positive test whether a straddles the line in which b lies
  159.  * returns 1 if yes, 0 if no.
  160.  */
  161.  
  162. int straddle(segment_t a, segment_t b)
  163.  
  164. {
  165.     sub(a.p, b.p);        /* a.p -> vector from b.p to a.p    */
  166.     sub(a.q, b.p);        /* a.q -> vector from b.p to a.q    */    
  167.     sub(b.p, b.q);        /* b.p -> vector in line b        */
  168.     
  169.     return (cross(b.p,a.p) * cross(b.p,a.q) < 0);
  170. }
  171.  
  172. /*
  173.  * test whether a and b intersect
  174.  * returns 1 if yes, 0 if no.
  175.  * args are two segment_t structures
  176.  */
  177.  
  178. #define intersect(a,b) (bounding (&a,&b) && straddle(a, b) && straddle(b,a))
  179.  
  180. #include <stdio.h>
  181.  
  182. int main(int argc, char **argv)
  183.  
  184. {
  185.     segment_t a, b;
  186.  
  187.     printf("enter two (x,y) line endpoints for line segment A: ");
  188.     scanf("%lf%lf%lf%lf",&a.p.x,&a.p.y,&a.q.x,&a.q.y);
  189.  
  190.     printf("enter two (x,y) line endpoints for line segment B: ");
  191.     scanf("%lf%lf%lf%lf",&b.p.x,&b.p.y,&b.q.x,&b.q.y);
  192.  
  193.     if (intersect(a,b)) 
  194.         puts("they intersect");
  195.     else
  196.         puts("they don't intersect");
  197.  
  198.     return 0;
  199. }
  200.  
  201.  
  202. A couple of sample runs should always be included:
  203.  
  204. anvil [18]:~>a.out
  205. enter two (x,y) line endpoints for line segment A: 0 0  1 1
  206. enter two (x,y) line endpoints for line segment B: 0 1  1 0
  207. they intersect
  208. anvil [19]:~>a.out
  209. enter two (x,y) line endpoints for line segment A: 0 0  1 1
  210. enter two (x,y) line endpoints for line segment B: 20 20  40 40
  211. they don't intersect
  212. -- 
  213.  
  214.